使用Python Pandas樞紐分析表掌握資料重塑。深入探討語法、進階技巧和全球資料分析的實用範例。
Python Pandas樞紐分析表:資料重塑的綜合指南
在資料分析的世界中,總結、彙總和重組資料的能力不僅僅是一項技能,更是一種超能力。原始資料通常像一本龐大而詳細的分類帳。它包含豐富的資訊,但難以解釋。為了提取有意義的見解,我們需要將此分類帳轉換為簡潔的摘要。這正是樞紐分析表擅長的地方,對於Python程式設計師來說,Pandas庫提供了一個強大而靈活的工具:pivot_table()。
本指南專為全球的資料分析師、科學家和Python愛好者設計。我們將深入研究Pandas樞紐分析表的機制,從基本概念到進階技巧。無論您是總結來自不同大陸的銷售額、分析跨地區的氣候資料,還是追蹤分佈式團隊的專案指標,掌握樞紐分析表都將從根本上改變您處理資料探索的方式。
什麼是樞紐分析表?
如果您曾經使用過Microsoft Excel或Google Sheets等試算表軟體,您可能熟悉樞紐分析表的概念。它是一個互動式表格,允許您重新組織和總結來自較大資料集的選定欄和列的資料,以獲得所需的報告。
樞紐分析表主要做兩件事:
- 彙總:它計算按一個或多個類別分組的數值資料的摘要統計資訊(如總和、平均值或計數)。
- 重塑:它將資料從「長」格式轉換為「寬」格式。它不是將所有值放在單一列中,而是將列中的唯一值「樞紐」到輸出中的新列中。
Pandas pivot_table()函數將這種強大的功能直接帶入您的Python資料分析工作流程中,從而實現可重複、可編寫腳本和可擴展的資料重塑。
設定您的環境和範例資料
在我們開始之前,請確保您已安裝Pandas庫。如果沒有,您可以使用pip(Python的套件安裝程式)進行安裝:
pip install pandas
現在,讓我們在我們的Python腳本或筆記本中匯入它:
import pandas as pd
import numpy as np
建立全球銷售資料集
為了使我們的範例具有實用性和全球相關性,我們將建立一個合成資料集,代表一家跨國電子商務公司的銷售資料。此資料集將包含來自不同地區、國家和產品類別的銷售資訊。
# Create a dictionary of data
data = {
'TransactionID': range(1, 21),
'Date': pd.to_datetime([
'2023-01-15', '2023-01-16', '2023-01-17', '2023-02-10', '2023-02-11',
'2023-02-12', '2023-03-05', '2023-03-06', '2023-03-07', '2023-01-20',
'2023-01-21', '2023-02-15', '2023-02-16', '2023-03-10', '2023-03-11',
'2023-01-18', '2023-02-20', '2023-03-22', '2023-01-25', '2023-02-28'
]),
'Region': [
'North America', 'Europe', 'Asia', 'North America', 'Europe', 'Asia', 'North America', 'Europe', 'Asia', 'Europe',
'Asia', 'North America', 'Europe', 'Asia', 'North America', 'Asia', 'Europe', 'North America', 'Europe', 'Asia'
],
'Country': [
'USA', 'Germany', 'Japan', 'Canada', 'France', 'India', 'USA', 'UK', 'China', 'Germany',
'Japan', 'USA', 'France', 'India', 'Canada', 'China', 'UK', 'USA', 'Germany', 'India'
],
'Product_Category': [
'Electronics', 'Apparel', 'Electronics', 'Books', 'Apparel', 'Electronics', 'Books', 'Electronics', 'Apparel',
'Apparel', 'Books', 'Electronics', 'Books', 'Apparel', 'Electronics', 'Books', 'Apparel', 'Books', 'Electronics', 'Electronics'
],
'Units_Sold': [10, 5, 8, 20, 7, 12, 15, 9, 25, 6, 30, 11, 18, 22, 14, 28, 4, 16, 13, 10],
'Unit_Price': [1200, 50, 900, 15, 60, 1100, 18, 950, 45, 55, 12, 1300, 20, 40, 1250, 14, 65, 16, 1150, 1050]
}
# Create DataFrame
df = pd.DataFrame(data)
# Calculate Revenue
df['Revenue'] = df['Units_Sold'] * df['Unit_Price']
# Display the first few rows of the DataFrame
print(df.head())
此資料集為我們提供了一個堅實的基礎,其中包含分類資料(地區、國家、產品類別)、數值資料(銷售單位、收入)和時間序列資料(日期)。
pivot_table()的剖析
Pandas pivot_table()函數功能非常強大。讓我們分解其最重要的參數:
pandas.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, margins_name='All')
- data:您要樞紐分析的DataFrame。
- values:包含要彙總的資料的欄。如果未指定,將使用所有剩餘的數值欄。
- index:其唯一值將構成新樞紐分析表行的欄。這有時稱為「分組鍵」。
- columns:其唯一值將被「樞紐」以形成新表欄的欄。
- aggfunc:應用於「values」的彙總函數。它可以是像「sum」、「mean」、「count」、「min」、「max」這樣的字串,也可以是像
np.sum這樣的函數。您也可以傳遞函數列表或字典,以將不同的函數應用於不同的欄。預設值為「mean」。 - fill_value:用於替換樞紐分析表中任何遺失結果 (NaN) 的值。
- margins:一個布林值。如果設定為
True,則它會為行和列新增小計(也稱為總計)。 - margins_name:當
margins=True時,包含總計的列/行的名稱。預設值為「All」。
您的第一個樞紐分析表:一個簡單的範例
讓我們從一個常見的業務問題開始:「每個產品類別產生的總收入是多少?」
為了回答這個問題,我們需要:
- 使用
Product_Category作為行(index)。 - 彙總
Revenue欄(values)。 - 使用總和作為我們的彙總函數(aggfunc)。
# Simple pivot table to see total revenue by product category
category_revenue = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
aggfunc='sum')
print(category_revenue)
輸出:
Revenue
Product_Category
Apparel 1645
Books 1184
Electronics 56850
我們立即獲得了一個清晰、簡潔的摘要。原始的20行列交易記錄已重塑為一個3列表,直接回答了我們的問題。這就是樞紐分析表的基本力量。
新增欄維度
現在,讓我們擴展一下。如果我們想查看每個產品類別的總收入,但也按地區細分呢?這就是columns參數的用武之地。
# Pivot table with index and columns
revenue_by_category_region = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
columns='Region',
aggfunc='sum')
print(revenue_by_category_region)
輸出:
Region Asia Europe North America Product_Category Apparel 1125.0 625.0 NaN Books 336.0 360.0 488.0 Electronics 13200.0 14550.0 29100.0
此輸出更加豐富。我們已將來自「Region」欄(「Asia」、「Europe」、「North America」)的唯一值樞紐到新欄中。我們現在可以輕鬆比較不同產品類別在不同地區的表現。我們還看到一個NaN(非數字)值。這表示我們的資料集中沒有記錄「North America」的「Apparel」銷售額。這本身就是有價值的資訊!
進階樞紐分析技巧
基礎知識功能強大,但pivot_table()的真正靈活性體現在其進階功能中。
使用fill_value處理遺失值
我們之前表格中的NaN是準確的,但為了報告或進一步計算,最好將其顯示為零。fill_value參數使此操作變得容易。
# Using fill_value to replace NaN with 0
revenue_by_category_region_filled = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
columns='Region',
aggfunc='sum',
fill_value=0)
print(revenue_by_category_region_filled)
輸出:
Region Asia Europe North America Product_Category Apparel 1125 625 0 Books 336 360 488 Electronics 13200 14550 29100
該表格現在更清晰,更易於閱讀,特別是對於非技術受眾而言。
使用多個索引(階層式索引)
如果您需要在多個類別上按行分組怎麼辦?例如,讓我們按Region細分銷售額,然後按每個地區內的Country細分。我們可以將欄列表傳遞給index參數。
# Multi-level pivot table using a list for the index
multi_index_pivot = pd.pivot_table(df,
values='Revenue',
index=['Region', 'Country'],
aggfunc='sum',
fill_value=0)
print(multi_index_pivot)
輸出:
Revenue
Region Country
Asia China 488
India 1760
Japan 10860
Europe France 1020
Germany 14440
UK 1115
North America Canada 17800
USA 12058
Pandas已在行上自動建立MultiIndex。此階層式結構非常適合深入研究您的資料並查看巢狀關係。您可以將相同的邏輯應用於columns參數以建立階層式欄。
使用多個彙總函數
有時,一個摘要統計資訊是不夠的。您可能想查看每個群組的總收入(總和)和平均交易規模(平均值)。您可以將函數列表傳遞給aggfunc。
# Using multiple aggregation functions
multi_agg_pivot = pd.pivot_table(df,
values='Revenue',
index='Region',
aggfunc=['sum', 'mean', 'count'])
print(multi_agg_pivot)
輸出:
sum mean count
Revenue Revenue Revenue
Region
Asia 13108.000000 2184.666667 6
Europe 16575.000000 2762.500000 6
North America 29858.000000 4976.333333 6
此單一命令為我們提供了一個全面的摘要:每個地區的總收入、每次交易的平均收入和交易數量。請注意Pandas如何建立階層式欄以保持輸出井然有序。
將不同的函數應用於不同的值
您可以獲得更精細的粒度。想像一下,您想查看Revenue的總和,但查看Units_Sold的平均值。您可以將字典傳遞給aggfunc,其中鍵是欄名稱(「values」),值是所需的彙總函數。
# Different aggregations for different values
dict_agg_pivot = pd.pivot_table(df,
index='Region',
values=['Revenue', 'Units_Sold'],
aggfunc={
'Revenue': 'sum',
'Units_Sold': 'mean'
},
fill_value=0)
print(dict_agg_pivot)
輸出:
Revenue Units_Sold
Region
Asia 13108 17.833333
Europe 16575 8.166667
North America 29858 14.333333
這種控制級別使pivot_table()成為用於複雜資料分析的首要工具。
使用margins計算總計
出於報告目的,通常需要有行和列的總計。margins=True引數在零額外努力的情況下提供了此功能。
# Adding totals with margins=True
revenue_with_margins = pd.pivot_table(df,
values='Revenue',
index='Product_Category',
columns='Region',
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='Grand Total') # Custom name for totals
print(revenue_with_margins)
輸出:
Region Asia Europe North America Grand Total Product_Category Apparel 1125 625 0 1750 Books 336 360 488 1184 Electronics 13200 14550 29100 56850 Grand Total 14661 15535 29588 59784
Pandas自動計算每行的總和(所有地區每個產品類別的總收入)和每列的總和(所有類別每個地區的總收入),以及右下角所有資料的總計。
實際用例:基於時間的分析
樞紐分析表不限於靜態類別。它們對於分析時間序列資料非常有用。讓我們找到每個月的總收入。
首先,我們需要從「Date」欄中提取月份。我們可以為此使用Pandas中的.dt存取子。
# Extract month from the Date column
df['Month'] = df['Date'].dt.month_name()
# Pivot to see monthly revenue by product category
monthly_revenue = pd.pivot_table(df,
values='Revenue',
index='Month',
columns='Product_Category',
aggfunc='sum',
fill_value=0)
# Optional: Order the months correctly
month_order = ['January', 'February', 'March']
monthly_revenue = monthly_revenue.reindex(month_order)
print(monthly_revenue)
輸出:
Product_Category Apparel Books Electronics Month January 250 360 23100 February 795 794 24250 March 705 30 9500
此表格為我們提供了每個類別在一段時間內的銷售業績的清晰檢視,使我們能夠輕鬆發現趨勢、季節性或異常情況。
pivot_table() vs. groupby():有什麼區別?
對於那些學習Pandas的人來說,這是一個常見的問題。這兩個函數密切相關,實際上,pivot_table()構建於groupby()之上。
groupby()是一個更通用和基本的操作。它根據某些標準對資料進行分組,然後讓您應用彙總函數。結果通常是一個帶有階層式索引的Pandas Series或DataFrame,但它仍然採用「長」格式。pivot_table()是一個專用工具,可以執行group-by,然後重塑資料。其主要目的是將資料從長格式轉換為寬格式,這通常更易於人類閱讀。
讓我們使用groupby()重新檢視我們的第一個範例:
# Same result as our first pivot table, but using groupby
category_revenue_groupby = df.groupby('Product_Category')['Revenue'].sum()
print(category_revenue_groupby)
結果是一個Pandas Series,在功能上等同於我們第一個樞紐分析表的DataFrame。但是,當您引入第二個分組鍵(如「Region」)時,差異就變得明顯了。
# Grouping by two columns
groupby_multi = df.groupby(['Product_Category', 'Region'])['Revenue'].sum()
print(groupby_multi)
輸出(帶有MultiIndex的Series):
Product_Category Region
Apparel Asia 1125
Europe 625
Books Asia 336
Europe 360
North America 488
Electronics Asia 13200
Europe 14550
North America 29100
Name: Revenue, dtype: int64
為了獲得與pivot_table(index='Product_Category', columns='Region')相同的「寬」格式,您需要使用groupby()後接unstack():
# Replicating a pivot table with groupby().unstack()
groupby_unstack = df.groupby(['Product_Category', 'Region'])['Revenue'].sum().unstack(fill_value=0)
print(groupby_unstack)
這會產生與我們的樞紐分析表帶欄完全相同的輸出。因此,您可以將pivot_table()視為groupby().aggregate().unstack()常用工作流程的便捷捷徑。
何時使用哪個?
- 當您想要人類可讀的寬格式輸出時,特別是對於報告或建立交叉表時,請使用
pivot_table()。 - 當您需要更大的靈活性、在資料處理管道中執行中間計算或寬格式不是您的最終目標時,請使用
groupby()。
效能和最佳實務
雖然pivot_table()功能強大,但重要的是有效率地使用它,特別是對於大型資料集。
- 先篩選,後樞紐:如果您只需要分析資料的子集(例如,去年的銷售額),請在應用樞紐分析表之前篩選DataFrame。這減少了函數必須處理的資料量。
- 使用分類類型:對於您經常在樞紐分析表中用作索引或欄的欄(如「Region」或「Product_Category」),請將它們轉換為Pandas中的「category」dtype。這可以顯著減少記憶體使用量並加速分組操作。
df['Region'] = df['Region'].astype('category') - 保持可讀性:避免建立帶有過多索引和欄的樞紐分析表。雖然有可能,但數百欄寬和數千列長的樞紐分析表可能會變得與原始原始資料一樣難以讀取。使用它來建立有針對性的摘要。
- 了解彙總:請注意您對
aggfunc的選擇。對價格使用「sum」沒有意義,而「mean」可能更合適。始終確保您的彙總與您嘗試回答的問題一致。
結論:您用於產生有見地的摘要的工具
Pandas pivot_table()函數是任何資料分析師工具包中不可或缺的工具。它提供了一種宣告式、表達式和強大的方法,可以從混亂、詳細的資料轉移到清晰、有見地的摘要。透過了解和掌握其核心組件(values、index、columns和aggfunc)並利用其進階功能(如多層索引、自訂彙總和邊距),您可以重塑您的資料,只需幾行Python程式碼即可回答複雜的業務問題。
下次當您面臨大型資料集時,請抵制滾動瀏覽無休止的行的衝動。相反,考慮一下您需要回答的問題以及樞紐分析表如何重塑您的資料以揭示隱藏在其中的故事。樞紐分析愉快!